import away3d.core.base.*;
import away3d.materials.*;
import away3d.modifiers.*;
import away3d.primitives.*;
import away3d.sprites.*;

import com.powerfl.frm.taf.*;

import flash.display.*;
import flash.filters.*;
import flash.media.*;

private function poolInit():void{
	_poolOrderD = new Vector.<TAForder>();
	_poolVectorOrderD = new Vector.<Vector.<TAForder>>();
	_poolTreeD = new Vector.<TAFtree>();
	_poolParamD = new Vector.<TAFparam>();
	_poolEachD = new Vector.<TAFeach>();
	_poolAwayVarD = new Vector.<TAFawayVar>();
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
final internal function collectMaterial( $material:Material ):void{
	if( $material is VideoMaterial ){
		poolCollectFlv( $material as VideoMaterial );
	}else if( $material is BitmapMaterial ){
		poolCollectBitmapMaterial( $material as BitmapMaterial );
	}else if( $material is ColorMaterial ){
		poolCollectColorMaterial( $material as ColorMaterial  );
	}else if( $material is WireframeMaterial ){
		poolCollectWireframeMaterial( $material as WireframeMaterial  );
	}
}
private function collectAwayChild( $child:Object3D ):void{
	if( $child is ObjectContainer3D ){
		poolCollectObjectContainer3D( $child as ObjectContainer3D );
	}else if( $child is Plane ){
		poolCollectPlane( $child as Plane );
	}else if( $child is Sprite3D ){
		poolCollectSprite3D( $child as Sprite3D );
	}
}
private function collectFilter( $filters:Array ):void{
	var key:*;
	for each( key in $filters ){
		if( key is BlurFilter ){
			poolCollectBlurFilter( key );
		}else if( key is GlowFilter ){
			poolCollectGlowFilter( key );
		}
	}
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolParamD:Vector.<TAFparam>;
private function poolPullParam():TAFparam{
	var result:TAFparam;
	if( SELF._poolParamD.length ){
		result = SELF._poolParamD.pop();
	}else{
		result = new TAFparam;
	}
	return result;
}
private function poolCollectParam( $param:TAFparam ):void{
	if( $param ){
		SELF._poolParamD[SELF._poolParamD.length] = $param.collect();
	}
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolEachD:Vector.<TAFeach>;
private function poolPullEach():TAFeach{
	var result:TAFeach;
	if( SELF._poolEachD.length ){
		result = SELF._poolEachD.pop();
	}else{
		result = new TAFeach;
	}
	return result;
}
private function poolCollectEach( $each:TAFeach ):void{
	SELF._poolEachD[SELF._poolEachD.length] = $each.collect();
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolOrderD:Vector.<TAForder>;
private function poolPullOrder():TAForder{
	var result:TAForder;
	if( SELF._poolOrderD.length ){
		result = SELF._poolOrderD.pop();
	}else{
		result = new TAForder;
	}
	return result;
}
private function poolCollectOrder( $order:TAForder ):void{
	SELF._poolOrderD[SELF._poolOrderD.length] = $order.collect();
}
private var _poolVectorOrderD:Vector.<Vector.<TAForder>>;
private function poolPullVectorOrder():Vector.<TAForder>{
	var result:Vector.<TAForder>;
	if( SELF._poolVectorOrderD.length ){
		result = SELF._poolVectorOrderD.pop();
	}else{
		result = new Vector.<TAForder>;
	}
	return result;
}
private function poolCollectVectorOrder( $order:Vector.<TAForder> ):void{
	$order.length = 0
	SELF._poolVectorOrderD[SELF._poolVectorOrderD.length] = $order;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolTreeD:Vector.<TAFtree>;
private function poolPullTree():TAFtree{
	var result:TAFtree;
	if( SELF._poolTreeD.length ){
		result = SELF._poolTreeD.pop();
	}else{
		result = new TAFtree;
	}
	return result;
}
private function poolCollectTree( $tree:TAFtree ):void{
	SELF._poolTreeD[SELF._poolTreeD.length] = $tree.collect();
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolResD:Vector.<TAFres>;
final private function poolPullRes():TAFres{
	var result:TAFres;
	if( SELF._poolResD === null ){
		SELF._poolResD = new Vector.<TAFres>();
	}
	if( SELF._poolResD.length ){
		result = SELF._poolResD.pop();
	}else{
		result = new TAFres;
	}
	return result;
}
final private function poolCollectRes( $var:TAFres ):void{
	SELF._poolResD[SELF._poolResD.length] = $var.collect();
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolAwayVarD:Vector.<TAFawayVar>;
final internal function poolPullAwayVar():TAFawayVar{
	var result:TAFawayVar;
	if( SELF._poolAwayVarD.length ){
		result = SELF._poolAwayVarD.pop();
	}else{
		result = new TAFawayVar;
	}
	return result;
}
final internal function poolCollectAwayVar( $var:TAFawayVar ):void{
	SELF._poolAwayVarD[SELF._poolAwayVarD.length] = $var.collect();
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolLoaderD:Vector.<TAFloader>;
final internal function poolPullLoader():TAFloader{
	var result:TAFloader;
	if( SELF._poolLoaderD === null ){
		SELF._poolLoaderD = new Vector.<TAFloader>();
	}
	if( SELF._poolLoaderD.length ){
		result = SELF._poolLoaderD.pop();
	}else{
		result = new TAFloader;
	}
	return result;
}
final internal function poolCollectLoader( $loader:TAFloader ):void{
	SELF._poolLoaderD[SELF._poolLoaderD.length] = $loader.collect();
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolTweenVarD:Vector.<TAFtweenVar>;
final internal function poolPullTweenVar():TAFtweenVar{
	var result:TAFtweenVar;
	if( SELF._poolTweenVarD === null ){
		SELF._poolTweenVarD = new Vector.<TAFtweenVar>();
	}
	if( SELF._poolTweenVarD.length ){
		result = SELF._poolTweenVarD.pop();
	}else{
		result = new TAFtweenVar;
	}
	return result;
}
final internal function poolCollectTweenVar( $var:TAFtweenVar ):void{
	SELF._poolTweenVarD[SELF._poolTweenVarD.length] = $var.collect();
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolSoundD:Vector.<TAFsound>;
final internal function poolPullSound( $sound:Sound ):TAFsound{
	var result:TAFsound;
	if( SELF._poolSoundD === null ){
		SELF._poolSoundD = new Vector.<TAFsound>();
	}
	if( SELF._poolSoundD.length ){
		result = SELF._poolSoundD.pop();
	}else{
		result = new TAFsound;
	}
	result._sound = $sound;
	return result;
}
final internal function poolCollectSound( $var:TAFsound ):void{
	SELF._poolSoundD[SELF._poolSoundD.length] = $var.collect();
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolBlurFilterD:Vector.<BlurFilter>;
final internal function poolPullBlurFilter():BlurFilter{
	var result:BlurFilter;
	if( SELF._poolBlurFilterD === null ){
		SELF._poolBlurFilterD = new Vector.<BlurFilter>();
	}
	if( SELF._poolBlurFilterD.length ){
		result = SELF._poolBlurFilterD.pop();
	}else{
		result = new BlurFilter;
	}
	return result;
}
final internal function poolCollectBlurFilter( $filter:BlurFilter ):void{
	SELF._poolBlurFilterD[SELF._poolBlurFilterD.length] = $filter;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolGlowFilterD:Vector.<GlowFilter>;
final internal function poolPullGlowFilter():GlowFilter{
	var result:GlowFilter;
	if( SELF._poolGlowFilterD === null ){
		SELF._poolGlowFilterD = new Vector.<GlowFilter>();
	}
	if( SELF._poolGlowFilterD.length ){
		result = SELF._poolGlowFilterD.pop();
	}else{
		result = new GlowFilter;
	}
	return result;
}
final internal function poolCollectGlowFilter( $filter:GlowFilter ):void{
	SELF._poolGlowFilterD[SELF._poolGlowFilterD.length] = $filter;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolDropFilterD:Vector.<DropShadowFilter>;
final internal function poolPullDropFilter():DropShadowFilter{
	var result:DropShadowFilter;
	if( SELF._poolDropFilterD === null ){
		SELF._poolDropFilterD = new Vector.<DropShadowFilter>();
	}
	if( SELF._poolDropFilterD.length ){
		result = SELF._poolDropFilterD.pop();
	}else{
		result = new DropShadowFilter;
	}
	return result;
}
final internal function poolCollectDropFilter( $filter:DropShadowFilter ):void{
	SELF._poolDropFilterD[SELF._poolDropFilterD.length] = $filter;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolBitmapMaterialD:Vector.<BitmapMaterial>;
private function poolPullBitmapMaterial( $bitmapData:BitmapData ):BitmapMaterial{
	var result:BitmapMaterial;
	if( SELF._poolBitmapMaterialD === null ){
		SELF._poolBitmapMaterialD = new Vector.<BitmapMaterial>();
	}
	if( SELF._poolBitmapMaterialD.length ){	
		result = SELF._poolBitmapMaterialD.pop();
	}else{
		result = new BitmapMaterial( $bitmapData );
	}
	result.bitmap = $bitmapData;
	result.smooth = true;
	return result;
}
private function poolCollectBitmapMaterial( $bitmapMaterial:BitmapMaterial ):void{
	$bitmapMaterial.alpha = 1;
	SELF._poolBitmapMaterialD[SELF._poolBitmapMaterialD.length] = $bitmapMaterial;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private function poolPullColorMaterial( $color:uint ):ColorMaterial{
	return new ColorMaterial( $color );
}
private function poolCollectColorMaterial( $colorMaterial:ColorMaterial ):void{
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private function poolPullWireframeMaterial( $color:uint, $thickness:Number ):WireframeMaterial{
	return new WireframeMaterial;
}
private function poolCollectWireframeMaterial( $wireframeMaterial:WireframeMaterial ):void{
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private function poolPullFlv( $flv:String, $loop:Boolean ):VideoMaterial{
	var result:VideoMaterial;
	result = new VideoMaterial;
	result.loop = $loop;
	result.file = $flv;
	result.seek( 0 );
	return result;
}
private function poolCollectFlv( $flv:VideoMaterial ):void{
	$flv.close();
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolObjectContainer3DD:Vector.<ObjectContainer3D>;
private function poolPullObjectContainer3D( $param:TAFparam ):ObjectContainer3D{
	var result:ObjectContainer3D;
	if( SELF._poolObjectContainer3DD === null ){
		SELF._poolObjectContainer3DD = new Vector.<ObjectContainer3D>();
	}
	if( SELF._poolObjectContainer3DD.length ){
		result = SELF._poolObjectContainer3DD.pop();
	}else{
		result = new ObjectContainer3D;
	}
	if( $param ){
		$param.apply( result );
	}
	return result;
}
private function poolCollectObjectContainer3D( $ObjectContainer3D:ObjectContainer3D ):void{
	$ObjectContainer3D.x = $ObjectContainer3D.y = $ObjectContainer3D.z = $ObjectContainer3D.rotationX = $ObjectContainer3D.rotationY = $ObjectContainer3D.rotationZ = 0;
	$ObjectContainer3D.scaleX = $ObjectContainer3D.scaleY = $ObjectContainer3D.scaleZ = 1;
	SELF._poolObjectContainer3DD[SELF._poolObjectContainer3DD.length] = $ObjectContainer3D;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolPlaneD:Vector.<Plane>;

private function poolPullPlane( $param:TAFparam ):Plane{
	var result:Plane, vars:TAFawayVar;
	if( SELF._poolPlaneD === null ){
		SELF._poolPlaneD = new Vector.<Plane>();
	}
	if( SELF._poolPlaneD.length ){
		result = SELF._poolPlaneD.pop();
	}else{
		result = new Plane;
	}
	if( $param ){
		vars = $param.vars;
		vars.materialCheck();
		if( vars._width === 0 && vars._height === 0 ){
			vars._autoSize = -1;
		}
		if( vars._rotationX === 0 ){
			vars.rotationX = 90;
			vars._rotationX = -1;
		}
		$param.apply( result );
	}
	return result;
}
private function poolCollectPlane( $plane:Plane ):void{
	$plane.alpha = $plane.scaleX = $plane.scaleY = $plane.scaleZ = 1;
	$plane.x = $plane.y = $plane.z = $plane.rotationX = $plane.rotationY = $plane.rotationZ = 0;
	$plane.width = $plane.height = 100;
	$plane.visible = true;
	$plane.pushback = $plane.pushfront = $plane.mouseEnabled = $plane.bothsides = $plane.useHandCursor = $plane.ownCanvas = false;
	if( $plane.ownSession ){
		$plane.ownSession = null;
	}
	$plane.material = null;
	$plane.back = null;
	$plane.segmentsW = $plane.segmentsH = 1;
	SELF._poolPlaneD[SELF._poolPlaneD.length] = $plane;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolCubeD:Vector.<Cube>;
private function poolPullCube( $param:TAFparam ):Cube{
	var result:Cube, vars:TAFawayVar;
	if( SELF._poolCubeD === null ){
		SELF._poolCubeD = new Vector.<Cube>();
	}
	if( SELF._poolCubeD.length ){
		result = SELF._poolCubeD.pop();
	}else{
		result = new Cube;
		result.mappingType = 'map6';
	}
	if( $param ){
		vars = $param.vars;
		vars.materialCheck();
		$param.apply( result );
	}
	return result;
}
private function poolCollectCube( $cube:Cube ):void{
	$cube.mouseEnabled = false;
	$cube.visible = true;
	$cube.bothsides = $cube.useHandCursor = $cube.ownCanvas = $cube.flip = false;
	$cube.material = null;
	$cube.back = null;
	$cube.alpha = $cube.scaleX = $cube.scaleY = $cube.scaleZ = 1;
	$cube.x = $cube.y = $cube.z = $cube.rotationX = $cube.rotationY = $cube.rotationZ = 0;
	$cube.width = $cube.height = $cube.depth = 100;
	$cube.segmentsW = $cube.segmentsH = $cube.segmentsD = 1;
	SELF._poolCubeD[SELF._poolCubeD.length] = $cube;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolSprite3DD:Vector.<Sprite3D>;
private function poolPullSprite3D( $param:TAFparam ):Sprite3D{
	var result:Sprite3D, vars:TAFawayVar;
	if( SELF._poolSprite3DD === null ){
		SELF._poolSprite3DD = new Vector.<Sprite3D>();
	}
	if( SELF._poolSprite3DD.length ){
		result = SELF._poolSprite3DD.pop();
	}else{
		result = new Sprite3D;
	}
	vars = $param.vars;
	vars.materialCheck();
	$param.apply( result );
	return result;
}
private function poolCollectSprite3D( $Sprite3D:Sprite3D ):void{
	$Sprite3D.material = null;
	$Sprite3D.scaling = 1;
	$Sprite3D.x = $Sprite3D.y = $Sprite3D.z = $Sprite3D.rotation = 0;
	$Sprite3D.width = $Sprite3D.height = 100;
	$Sprite3D.visible = true;
	SELF._poolSprite3DD[SELF._poolSprite3DD.length] = $Sprite3D;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolHeightMapModifierD:Vector.<HeightMapModifier>;
private function poolPullHeightMapModifier( $mesh:Mesh, $heightMap:BitmapData, $channel:uint, $maxLevel:Number, $scale:Number, $offset:Number ):HeightMapModifier{
	var result:HeightMapModifier;
	if( SELF._poolHeightMapModifierD === null ){
		SELF._poolHeightMapModifierD = new Vector.<HeightMapModifier>();
	}
	if( SELF._poolHeightMapModifierD.length ){
		result = SELF._poolHeightMapModifierD.pop();
	}else{
		result = new HeightMapModifier;
	}
	result.mesh = $mesh;
	result.heightMap = $heightMap;
	result.channel = $channel;
	result.maxLevel = $maxLevel;
	result.scale = $scale;
	result.offset = $offset;
	return result;
}
private function poolCollectHeightMapModifier( $map:HeightMapModifier ):void{
	$map.mesh = null;
	$map.heightMap = null;
	SELF._poolHeightMapModifierD[SELF._poolHeightMapModifierD.length] = $map;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------
private var _poolTAFbitmapBlitChildD:Vector.<TAFbitmapBlitChild>;
private function poolPullTAFbitmapBlitChild( $param:TAFparam ):TAFbitmapBlitChild{
	var result:TAFbitmapBlitChild, vars:TAFawayVar;
	if( SELF._poolTAFbitmapBlitChildD === null ){
		SELF._poolTAFbitmapBlitChildD = new Vector.<TAFbitmapBlitChild>();
	}
	if( SELF._poolTAFbitmapBlitChildD.length ){
		result = SELF._poolTAFbitmapBlitChildD.pop();
	}else{
		result = new TAFbitmapBlitChild;
	}
	if( $param ){
		vars = $param.vars;
		vars.materialCheck();
		$param.apply( result );
	}
	return result;
}
private function poolCollectTAFbitmapBlitChild( $child:TAFbitmapBlitChild ):void{
	SELF._poolTAFbitmapBlitChildD[SELF._poolTAFbitmapBlitChildD.length] = $child.collect();
}